home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / What's New? / Development Kits / USBDDK_v1.0.1_updated / Examples / USBModem / ModemDriver.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-29  |  33.4 KB  |  1,323 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        ModemDriver.c
  3.  
  4.     Contains:    Code for USB Modem driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <DriverServices.h>
  13.  
  14. #include "Modem.h"
  15. #include "ModemDriver.h"
  16. #include "ShimSerialHAL.h"
  17.  
  18. static serPB     gSerialGlobals;
  19. static USBPB    syncPB, interruptPB, readPB, writePB, stallPB, delayPB;
  20.  
  21. /************************************************************************************/
  22. //
  23. //    immediateError
  24. //
  25. //    Determines whether it's an error or just pending.
  26. //
  27. /************************************************************************************/
  28.  
  29. static Boolean immediateError(OSStatus err)
  30. {
  31.     return ((err != kUSBPending) && (err != noErr));
  32. }
  33.  
  34. /************************************************************************************/
  35. //
  36. //    ConfigurationHandler
  37. //
  38. //    Configures the USB Serial Device (Modem).
  39. //
  40. /************************************************************************************/
  41.  
  42. static void ConfigurationHandler(USBPB *pb)
  43. {
  44. serPB                     *sp = &gSerialGlobals;
  45. USBEndPointDescriptor     *eDesc;
  46. OSStatus                err;
  47.  
  48.     TraceMessage(0, "\pEntering ConfigurationHandler");
  49.     
  50.     if(pb->usbStatus != noErr)
  51.     {
  52.         if((sp->onError == kReset) && (sp->retries > 0))
  53.         {
  54.             /* no idea what to do now?? */
  55.             USBExpertFatalError(sp->deviceRef, pb->usbStatus, sp->errorString, pb->usbRefcon);
  56.             
  57.             /* Mark port as errored */
  58.         }
  59.         else
  60.         {
  61.             StatusMessage(sp->deviceRef, sp->errorString, pb->usbStatus);
  62.             pb->usbRefcon = sp->onError;
  63.  
  64.             USBClearPipeStallByReference(pb->usbReference);
  65.             
  66.             /* we'll delay coming back to here */
  67.             sp->retries--;
  68.  
  69.             pb->usbReqCount = 0;
  70.             /* pb->usbFlags = kUSBtaskTime */
  71.             USBDelay(pb);
  72.  
  73.         }
  74.         
  75.         return;
  76.     }
  77.  
  78.     sp->onError = kReset;
  79.  
  80.     do{switch(pb->usbRefcon++)
  81.     {
  82.         case kStartConfig:
  83.             noteError("\pModem Driver driver does not recognize device (we'll try to config. it anyway)");            
  84.             if(sp->deviceDescriptor->numConf != 2)
  85.             {
  86.                 StatusMessage(sp->deviceRef, sp->errorString, 0);
  87.                 // break;    /* Now what ?? */
  88.             }
  89.             
  90.             /* Configure device to single configuration */
  91.             pb->usbBMRequestType = USBMakeBMRequestType(kUSBNone, kUSBStandard, kUSBDevice);            
  92.             
  93.             pb->usbBRequest = kUSBRqSetConfig;
  94.             pb->usbWValue = 2; /* select config #2 - seems config 1 is Win95 specific */
  95.             pb->usbWIndex = 0;
  96.             pb->usbReqCount = 0;
  97.             pb->usbBuffer = nil;
  98.             sp->onError = 1;
  99.  
  100.             noteError("\pModem driver Setting Config");            
  101.             if(immediateError(err = USBDeviceRequest(pb)))
  102.             {
  103.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  104.             }        
  105.         break;
  106.  
  107.         case kGetConfig:
  108.             /* get the full config descriptor */
  109.             pb->pbVersion = kUSBCurrentPBVersion;
  110.             pb->usbWValue = 1;
  111.             if (sp->retries > 0)
  112.             {
  113.                 sp->onError = kGetConfig;
  114.             } else {
  115.                 sp->onError = kReset;
  116.             }
  117.             noteError("\pModem driver getting full config descriptor");            
  118.             if(immediateError(err = USBGetFullConfigurationDescriptor(pb)))
  119.             {
  120.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  121.             }
  122.         
  123.         break;
  124.  
  125.         case kGetDataInterface:
  126.             /* remember the full config descriptor */
  127.             sp->conf = pb->usbBuffer;
  128.             StatusMessage(sp->deviceRef, "\pConfiguration Descriptor - ", (unsigned long)sp->conf);
  129.             
  130.             /* find the interface */
  131.             pb->usbReqCount = 0;
  132.             pb->usbClassType = kUSBDataClass;        /* data class */
  133.             pb->usbSubclass = 0;        /* any subclass */
  134.             pb->usbProtocol = 0;        /* any protocol */
  135.             pb->usbWValue = 0;        /* alt */
  136.             if (sp->retries > 0)
  137.             {
  138.                 sp->onError = kGetDataInterface;
  139.             } else {
  140.                 sp->onError = kReset;
  141.             }
  142.             
  143.             noteError("\pModem driver parsing the Data interface");            
  144.             if(immediateError(err = USBFindNextInterfaceDescriptorImmediate(pb)))
  145.             {    /* this should return immediately */
  146.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  147.             }
  148.             
  149.             /* remember the current position */
  150.             sp->interface = pb->usbBuffer;
  151.             StatusMessage(sp->deviceRef, "\pData Interface Descriptor - ", (unsigned long)sp->interface);
  152.             
  153.             sp->interfaceOffset = pb->usbReqCount;
  154.             
  155.             /* Find the out endpoint */
  156.             pb->usbFlags = kUSBOut;
  157.             pb->usbClassType = kUSBBulk;
  158.             pb->usbSubclass = 0;            /* Find the first one */
  159.             
  160.             noteError("\pModem driver parsing the bulk out endpoint");            
  161.             if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
  162.             {    /* this should return immediately */
  163.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  164.             }
  165.             
  166.             /* Save away the device ref, it gets overwritten by the open */
  167.             sp->deviceRef = pb->usbReference;
  168.             
  169.             pb->usbFlags = kUSBOut;
  170.             /* The params are set up correctly so open it */
  171.             //eDesc = pb->usbBuffer;
  172.             //pb->usbValue = USBToHostWord(eDesc->maxPacketSize);
  173.             // max packet size is now returned in usbValue
  174.             
  175.             noteError("\pModem driver opening bulk out pipe");            
  176.             if(immediateError(err = USBOpenPipe(pb)))
  177.             {
  178.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  179.             }        
  180.             
  181.             
  182.         break;
  183.     
  184.         case kGetEndpoint:
  185.             /* Out Endpoint is open */
  186.  
  187.             /* remember the ref */
  188.             sp->bulkOut = pb->usbReference;
  189.             StatusMessage(sp->deviceRef, "\pBulk Out Endpoint - ", sp->bulkOut);
  190.             
  191.             /* Find the in endpoint */
  192.  
  193.             /* restore the device ref, it gets overwritten by the open */
  194.             pb->usbReference = sp->deviceRef;
  195.             
  196.             /* set search back to just found interface */
  197.             pb->usbBuffer = sp->interface;
  198.             pb->usbReqCount = sp->interfaceOffset;
  199.             
  200.             pb->usbFlags = kUSBIn;
  201.             pb->usbClassType = kUSBBulk;
  202.             pb->usbSubclass = 0;            /* Find the first one */
  203.             if (sp->retries > 0)
  204.             {
  205.                 sp->onError = kGetEndpoint;
  206.             } else {
  207.                 sp->onError = kReset;
  208.             }
  209.             
  210.             noteError("\pModem driver parsing the bulk in endpoint");            
  211.             if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
  212.             {    /* this should return immediatly */
  213.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  214.             }
  215.             
  216.             pb->usbFlags = kUSBIn;
  217.             /* The params are set up correctly so open it */
  218.             eDesc = pb->usbBuffer;
  219.             pb->usbProtocol = USBToHostWord(eDesc->maxPacketSize);
  220.  
  221.             noteError("\pModem driver opening bulk in pipe");            
  222.             if(immediateError(err = USBOpenPipe(pb)))
  223.             {
  224.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  225.             }        
  226.             
  227.             
  228.         break;
  229.     
  230.         case kGetCommInterface:
  231.             /* In Endpoint is open */
  232.  
  233.             /* remember the ref */
  234.             sp->bulkIn = pb->usbReference;
  235.             StatusMessage(sp->deviceRef, "\pBulk In Endpoint - ", sp->bulkIn);
  236.             
  237.             /* find the Comm Class interface */
  238.             pb->usbBuffer = sp->conf;            /* set it back to config desc. */
  239.             pb->usbReqCount = 0;
  240.             pb->usbFlags = 0;
  241.             pb->usbClassType = kUSBCommClass;        /* Comm class */
  242.             pb->usbSubclass = 2;        /* Abstract Control Model */
  243.             pb->usbProtocol = 1;        /* Hayes protocol */
  244.             pb->usbWValue = 0;        /* alt */
  245.             if (sp->retries > 0)
  246.             {
  247.                 sp->onError = kGetCommInterface;
  248.             } else {
  249.                 sp->onError = kReset;
  250.             }
  251.             
  252.             noteError("\pModem driver parsing the Class interface");            
  253.             if(immediateError(err = USBFindNextInterfaceDescriptorImmediate(pb)))
  254.             {    /* this should return immediately */
  255.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  256.             }
  257.             
  258.             /* remember the current position */
  259.             sp->clinterface = pb->usbBuffer;
  260.             StatusMessage(sp->deviceRef, "\pClass Interface Descriptor - ", (unsigned long)sp->clinterface);
  261.             
  262.             sp->clinterfaceOffset = pb->usbReqCount;
  263.             
  264.             /* Find the interrupt endpoint */
  265.  
  266.             /* restore the device ref, it gets overwritten by the open */
  267.             pb->usbReference = sp->deviceRef;
  268.             
  269.             /* set search back to just found interface */
  270.             pb->usbBuffer = sp->clinterface;
  271.             pb->usbReqCount = sp->clinterfaceOffset;
  272.             
  273.             pb->usbFlags = kUSBIn;
  274.             pb->usbClassType = kUSBInterrupt;
  275.             pb->usbSubclass = 0;            /* Find the first one */
  276.             if (sp->retries > 0)
  277.             {
  278.                 sp->onError = kGetCommInterface;
  279.             } else {
  280.                 sp->onError = kReset;
  281.             }
  282.             
  283.             noteError("\pModem Driver parsing the interrupt in endpoint");            
  284.             if(immediateError(err = USBFindNextEndpointDescriptorImmediate(pb)))
  285.             {    /* this should return immediatly */
  286.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  287.             }
  288.             
  289.             pb->usbFlags = kUSBIn;
  290.             /* The params are set up correctly so open it */
  291.             eDesc = pb->usbBuffer;
  292.             pb->usbProtocol = USBToHostWord(eDesc->maxPacketSize);
  293.  
  294.             noteError("\pModem Driver opening interrupt in pipe");            
  295.             if(immediateError(err = USBOpenPipe(pb)))
  296.             {
  297.                 USBExpertFatalError(sp->deviceRef, err, sp->errorString, 0);
  298.             }        
  299.                         
  300.         break;
  301.  
  302.         case kConfigDone:
  303.             /* Interrupt is open */
  304.  
  305.             /* remember the ref */
  306.             sp->interrupt = pb->usbReference;
  307.             StatusMessage(sp->deviceRef, "\pInterrupt In Endpoint - ", sp->interrupt);
  308.             
  309.             StartStatusMonitor(sp->interrupt);
  310.             
  311.             // device is fully configured, ready for somebody to set the baud rate, etc.
  312.             // and start reading/writing to the bulk endpoints
  313.             syncPB.usbStatus = kAvailableStatus;
  314.             StatusMessage(sp->deviceRef, "\pModem configuration complete.", 0);
  315.         break;
  316.     
  317.         default:
  318.             noteError("\pInternal Error unused case in Modem Configuration handler");            
  319.             StatusMessage(sp->deviceRef, sp->errorString, (pb->usbRefcon-1));
  320.         break;
  321.     }
  322.     break;    /* only execute once, unless continue used */
  323.     }while(1);    /* so case can be reentered with a continue */
  324. }
  325.  
  326. UInt16    statusData[8];
  327.  
  328. /************************************************************************************/
  329. //
  330. //    ResetInterruptPB
  331. //
  332. //    Re-initialize the interrupt PB.
  333. //
  334. /************************************************************************************/
  335.  
  336. static void ResetInterruptPB(USBPB *pb)
  337. {
  338.     pb->usbReqCount = 16;
  339.     pb->usbBuffer = &statusData;
  340.     pb->usbStatus = noErr;
  341. }
  342.  
  343. UInt8     Intrretries = 0;
  344.  
  345. /************************************************************************************/
  346. //
  347. //    interruptCompletion
  348. //
  349. //    Interrupt completion handler.
  350. //
  351. /************************************************************************************/
  352.  
  353. static void interruptCompletion(USBPB *pb)
  354. {
  355.     serPB         *sp = &gSerialGlobals;
  356.     OSStatus    err;
  357.     unsigned char        newErrs = 0;
  358.     ShimSerialGlobals    *globals = gGlobals;
  359.     
  360.     TraceMessage(0, "\pEntering interruptCompletion");
  361.     
  362.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  363.     {
  364.         if (pb->usbStatus != noErr)
  365.         {
  366.             StatusMessage(sp->deviceRef, "\pModemDriver: interruptCompletion error ", pb->usbStatus);
  367.             if (pb->usbStatus == kUSBEndpointStallErr)
  368.             {
  369.                 ClearDevice();
  370.             }
  371.             USBClearPipeStallByReference(gSerialGlobals.interrupt);
  372.             
  373.             Intrretries++;
  374.             if (Intrretries > 10)
  375.                 return;                    // we'll just give up for now
  376.                 
  377.             DoDelay();
  378.  
  379.         } else {
  380.             Intrretries = 0;
  381.             TraceMessage(0, "\pInterrupt received");
  382.             if ((pb->usbActCount > 2) && ((statusData[0] & 0x00FF) == kSerialState))
  383.             {
  384.                 sp->modemUSBStatus = HostToUSBWord(statusData[4]);
  385.                 
  386.                 if (sp->modemUSBStatus & kUSBParityErr) 
  387.                     newErrs |= parityErr;
  388.                 if (sp->modemUSBStatus & kUSBFramingErr) 
  389.                     newErrs |= framingErr;
  390.                 if (sp->modemUSBStatus & kUSBHwOverRunErr) 
  391.                     newErrs |= hwOverrunErr;
  392.                     
  393.                 globals->serStat.cumErrs |= newErrs;
  394.                 StatusMessage(sp->deviceRef, "\pModem Serial state - ", sp->modemUSBStatus);
  395.             }
  396.     }
  397.         
  398.     ResetInterruptPB(pb);
  399.  
  400.     if(immediateError(err = USBIntRead(pb)))
  401.     {
  402.             StatusMessage(sp->deviceRef, "\pCouldn't queue interrupt read!", err);
  403.         }
  404.     }    
  405. }
  406.  
  407. /************************************************************************************/
  408. //
  409. //    StartStatusMonitor
  410. //
  411. //    Kick off the interrupt mechanism.
  412. //
  413. /************************************************************************************/
  414.  
  415. static void StartStatusMonitor(USBPipeRef interruptPipe)
  416. {
  417.     USBPB        *pb = &interruptPB;
  418.     serPB         *sp = &gSerialGlobals;
  419.     OSStatus    err;
  420.     
  421.     TraceMessage(0, "\pEntering StartStatusMonitor");
  422.     
  423.     InitializePB(pb, interruptPipe, interruptCompletion);
  424.  
  425.     ResetInterruptPB(pb);
  426.  
  427.     if(immediateError(err = USBIntRead(pb)))
  428.     {
  429.         StatusMessage(sp->deviceRef, "\pCouldn't start interrupt read!", err);
  430.     }        
  431.  
  432. }
  433.  
  434. /************************************************************************************/
  435. //
  436. //    syncCompletion
  437. //
  438. //    Completion handler for all sync (setup) requests.
  439. //
  440. /************************************************************************************/
  441.  
  442. static void syncCompletion(USBPB *pb)
  443. {
  444.     serPB     *sp = &gSerialGlobals;
  445.  
  446.     TraceMessage(0, "\pEntering syncCompletion");
  447.  
  448.     if (pb->usbStatus != noErr)
  449.     {
  450.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pModemDriver: syncCompletion err for bRequest", pb->usbBRequest);
  451.         if (pb->usbStatus == kUSBEndpointStallErr)
  452.         {
  453. //            ClearDevice();
  454.         }
  455.         USBClearPipeStallByReference(pb->usbReference);
  456.     }
  457.         
  458.     pb->usbStatus = kAvailableStatus;
  459. }
  460.  
  461. /************************************************************************************/
  462. //
  463. //    TimeoutPrevRequest
  464. //
  465. //    Timeout for all sync. requests.
  466. //
  467. /************************************************************************************/
  468.  
  469. Boolean TimeoutPrevRequest(void)
  470. {
  471.     USBPB        *pb = &syncPB;
  472.     serPB         *sp = &gSerialGlobals;
  473.     AbsoluteTime    startTime;
  474.     Duration        elapsedTime;
  475.  
  476.     if (pb->usbStatus == kAvailableStatus)
  477.         return false;
  478.     
  479.     startTime = UpTime();
  480.  
  481.     while (pb->usbStatus != kAvailableStatus){
  482.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  483.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  484.         if (elapsedTime > 100*durationMillisecond){
  485.             StatusMessage(sp->deviceRef, "\pModem driver, device request timeout - aborting", 0);
  486.             USBAbortPipeByReference(pb->usbReference);
  487.             return true;
  488.         }
  489.     }
  490.     return false;
  491. }
  492.  
  493. /************************************************************************************/
  494. //
  495. //    TimeoutStallRequest
  496. //
  497. //    Timeout for all stall clear requests.
  498. //
  499. /************************************************************************************/
  500.  
  501. Boolean TimeoutStallRequest(void)
  502. {
  503.     USBPB            *pb = &stallPB;
  504.     serPB             *sp = &gSerialGlobals;
  505.     AbsoluteTime    startTime;
  506.     Duration        elapsedTime;
  507.  
  508.     if (pb->usbStatus == kAvailableStatus)
  509.         return false;
  510.     
  511.     startTime = UpTime();
  512.  
  513.     while (pb->usbStatus != kAvailableStatus){
  514.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  515.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  516.         if (elapsedTime > 100*durationMillisecond){
  517.             StatusMessage(sp->deviceRef, "\pModem driver, Stall timeout - aborting", 0);
  518.             USBAbortPipeByReference(pb->usbReference);
  519.             return true;
  520.         }
  521.     }
  522.     return false;
  523. }
  524.  
  525. /************************************************************************************/
  526. //
  527. //    TimeoutDelayRequest
  528. //
  529. //    Timeout for delay requests.
  530. //
  531. /************************************************************************************/
  532.  
  533. Boolean TimeoutDelayRequest(void)
  534. {
  535.     USBPB            *pb = &delayPB;
  536.     serPB             *sp = &gSerialGlobals;
  537.     AbsoluteTime    startTime;
  538.     Duration        elapsedTime;
  539.  
  540.     if (pb->usbStatus == kAvailableStatus)
  541.         return false;
  542.     
  543.     startTime = UpTime();
  544.  
  545.     while (pb->usbStatus != kAvailableStatus){
  546.         elapsedTime = AbsoluteDeltaToDuration(UpTime(), startTime);
  547.         if (elapsedTime < 0) elapsedTime = elapsedTime/(-1000);      // make sure it's in milliseconds
  548.         if (elapsedTime > 100*durationMillisecond){
  549.             return true;
  550.         }
  551.     }
  552.     return false;
  553. }
  554.  
  555. /************************************************************************************/
  556. //
  557. //    USBSetBaudRate
  558. //
  559. //    Set up and send SetLineCoding request for baud rate only.
  560. //
  561. /************************************************************************************/
  562.  
  563. void USBSetBaudRate(UInt32 baudRate)
  564. {
  565.     USBPB        *pb = &syncPB;
  566.     serPB         *sp = &gSerialGlobals;
  567.     OSStatus     err;
  568.     UInt16        temp = 0;
  569.     UInt16        rateh;
  570.     Boolean        setdte = false;
  571.     
  572.     TraceMessage(0, "\pEntering USBSetBaudRate");
  573.     
  574.     if (TimeoutPrevRequest())
  575.         return;
  576.     
  577.     if (baudRate == kMaxBaudRate)        // We're going to lock to max for the moment
  578.     {
  579.     
  580.         // convert baudrate            I hate Intel...
  581.         temp = baudRate % 0x10000;
  582.         rateh = USBToHostWord(temp);
  583.         if (rateh != sp->Line_Settings.DTERate1)
  584.         {
  585.             sp->Line_Settings.DTERate1 = rateh;
  586.             setdte = true;
  587.         }
  588.         temp = baudRate / 0x10000;
  589.         rateh = USBToHostWord(temp);
  590.         if (rateh != sp->Line_Settings.DTERate2)
  591.         {
  592.             sp->Line_Settings.DTERate2 = rateh;
  593.             setdte = true;
  594.         }
  595.     
  596.         // Only do it if it's changing
  597.         if (setdte)
  598.         {        
  599.             pb->usbStatus = noErr;
  600.             pb->pbVersion = kUSBCurrentPBVersion;
  601.             pb->usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);    
  602.             pb->usbBRequest = kSetLineCoding;
  603.             pb->usbWValue = 0;
  604.             pb->usbWIndex = 1; 
  605.             pb->usbReqCount = sizeof(sp->Line_Settings)-1;
  606.             pb->usbBuffer = &sp->Line_Settings;
  607.  
  608.             if(immediateError(err = USBDeviceRequest(pb)))
  609.             {
  610.                 StatusMessage(sp->deviceRef, "\pModem driver Setting baud rate", err);
  611.                 pb->usbStatus = kAvailableStatus;
  612.             }
  613.         }
  614.     }
  615. }
  616.  
  617. /************************************************************************************/
  618. //
  619. //    USBSetLineCoding
  620. //
  621. //    Set up and send SetLineCoding Request for all settings.
  622. //
  623. /************************************************************************************/
  624.  
  625. void USBSetLineCoding(LineParms Line_Coding)
  626. {
  627.     USBPB        *pb = &syncPB;
  628.     serPB         *sp = &gSerialGlobals;
  629.     OSStatus     err;
  630.     Boolean        setcoding = false;
  631.     
  632.     TraceMessage(0, "\pEntering USBSetLineCoding");
  633.     
  634.     if (TimeoutPrevRequest())
  635.         return;
  636.         
  637.     // save the settings only if they've changed
  638.     if (Line_Coding.CharFormat != sp->Line_Settings.CharFormat)
  639.     {
  640.         sp->Line_Settings.CharFormat = Line_Coding.CharFormat;
  641.         setcoding = true;
  642.     }
  643.     if (Line_Coding.ParityType != sp->Line_Settings.ParityType)
  644.     {
  645.         sp->Line_Settings.ParityType = Line_Coding.ParityType;
  646.         setcoding = true;
  647.     }
  648.     if (Line_Coding.DataBits != sp->Line_Settings.DataBits)
  649.     {
  650.         sp->Line_Settings.DataBits = Line_Coding.DataBits;
  651.         setcoding = true;
  652.     }
  653.     
  654.     // Don't do this if they haven't changed
  655.     if (setcoding)
  656.     {
  657.         pb->usbStatus = noErr;
  658.         pb->pbVersion = kUSBCurrentPBVersion;
  659.         pb->usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);                
  660.         pb->usbBRequest = kSetLineCoding;
  661.         pb->usbWValue = 0;
  662.         pb->usbWIndex = 1; 
  663.         pb->usbReqCount = sizeof(sp->Line_Settings)-1;
  664.         pb->usbBuffer = &sp->Line_Settings;
  665.  
  666.         if(immediateError(err = USBDeviceRequest(pb)))
  667.         {
  668.             StatusMessage(sp->deviceRef, "\pModem driver Setting Line Coding", err);
  669.             pb->usbStatus = kAvailableStatus;
  670.         }
  671.     }
  672. }
  673.  
  674. /************************************************************************************/
  675. //
  676. //    USBSetControlLineState
  677. //
  678. //    Set up and send SetControlLineState (DTR and RTS).
  679. //
  680. /************************************************************************************/
  681.  
  682. void USBSetControlLineState(void)
  683. {
  684.     USBPB        *pb = &syncPB;
  685.     serPB         *sp = &gSerialGlobals;
  686.     OSStatus     err;
  687.     
  688.     TraceMessage(0, "\pEntering USBSetControlLineState");
  689.     
  690.     if (TimeoutPrevRequest())
  691.         return;
  692.  
  693.     pb->usbStatus = noErr;
  694.     pb->pbVersion = kUSBCurrentPBVersion;
  695.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
  696.     pb->usbBRequest = kSetControlLineState;
  697.     pb->usbWValue = USBToHostWord(sp->lineState);
  698.     pb->usbWIndex = 1; 
  699.     pb->usbReqCount = 0;
  700.     pb->usbBuffer = 0;
  701.  
  702.     if(immediateError(err = USBDeviceRequest(pb)))
  703.     {
  704.         StatusMessage(sp->deviceRef, "\pModem driver Setting Control Line State", err);
  705.         pb->usbStatus = kAvailableStatus;
  706.     }
  707. }
  708.  
  709. /************************************************************************************/
  710. //
  711. //    USBSetDTRState
  712. //
  713. //    Set the DTR state.
  714. //
  715. /************************************************************************************/
  716.  
  717. void USBSetDTRState(Boolean state)
  718. {
  719.     serPB     *sp = &gSerialGlobals;
  720.  
  721.     TraceMessage(0, "\pEntering USBSetDTRState");
  722.  
  723.     if (state)
  724.     {
  725.         sp->lineState |= kDTROn;
  726.     } else {
  727.         if (!sp->DTRClose)
  728.             sp->lineState &= (kDTROff + kRTSOn);
  729.     }
  730. }
  731.  
  732. /************************************************************************************/
  733. //
  734. //    USBSetRTSState
  735. //
  736. //    Set the RTS state.
  737. //
  738. /************************************************************************************/
  739.  
  740. void USBSetRTSState(Boolean state)
  741. {
  742.     serPB     *sp = &gSerialGlobals;
  743.  
  744.     TraceMessage(0, "\pEntering USBSetRTSState");
  745.  
  746.     if (state)
  747.     {
  748.         sp->lineState |= kRTSOn;
  749.     } else {
  750.         sp->lineState &= (kRTSOff + kDTROn);
  751.     }
  752. }
  753.  
  754. /************************************************************************************/
  755. //
  756. //    USBSendBreak
  757. //
  758. //    Set up and send break request.
  759. //
  760. /************************************************************************************/
  761.  
  762. void USBSendBreak(Boolean state)
  763. {
  764.     USBPB        *pb = &syncPB;
  765.     serPB         *sp = &gSerialGlobals;
  766.     OSStatus     err;
  767.     
  768.     TraceMessage(0, "\pEntering USBSendBreak");
  769.     
  770.     if (TimeoutPrevRequest())
  771.         return;
  772.  
  773.     pb->usbStatus = noErr;
  774.     pb->pbVersion = kUSBCurrentPBVersion;
  775.     pb->usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBClass, kUSBInterface);
  776.     pb->usbBRequest = kSendBreak;
  777.     if (state)
  778.     {
  779.         pb->usbWValue = kBreakOn;
  780.     } 
  781.     else 
  782.     {
  783.         pb->usbWValue = kBreakOff;
  784.     }
  785.     pb->usbWIndex = 1; 
  786.     pb->usbReqCount = 0;
  787.     pb->usbBuffer = 0;
  788.  
  789.     if(immediateError(err = USBDeviceRequest(pb)))
  790.     {
  791.         StatusMessage(sp->deviceRef, "\pModem driver Setting Break State", err);
  792.         pb->usbStatus = kAvailableStatus;
  793.     }
  794. }
  795.  
  796. /************************************************************************************/
  797. //
  798. //    USBSetCloseDTR
  799. //
  800. //    Set the state of DTR on close.
  801. //
  802. /************************************************************************************/
  803.  
  804. void USBSetCloseDTR(void)
  805. {
  806.     serPB     *sp = &gSerialGlobals;
  807.  
  808.     TraceMessage(0, "\pEntering USBSetCloseDTR");
  809.  
  810.     sp->DTRClose = true;
  811. }
  812.  
  813. /************************************************************************************/
  814. //
  815. //    USBGetDCDValue
  816. //
  817. //    Gets the current state of CD.
  818. //
  819. /************************************************************************************/
  820.  
  821. UInt8 USBGetDCDValue(void)
  822. {
  823.     serPB     *sp = &gSerialGlobals;
  824.     UInt8    dcd = 0;
  825.  
  826.     TraceMessage(0, "\pEntering USBGetDCDValue");
  827.  
  828.     if (sp->modemUSBStatus & kUSBDCD) 
  829.         dcd = 1;
  830.         
  831.     return dcd;
  832. }
  833.  
  834. /************************************************************************************/
  835. //
  836. //    ModemDriverEntry
  837. //
  838. //    Initializes and starts the whole show.
  839. //
  840. /************************************************************************************/
  841.  
  842. void modemDriverEntry(USBDeviceRef device, USBDeviceDescriptor *desc)
  843. {
  844. static Boolean                 beenThereDoneThat = false;
  845. static USBDeviceDescriptor     ourDeviceDescriptor;
  846.  
  847.     DebugMessage("\pEntering modemDriverEntry - Sync. point");
  848.         
  849.     if(beenThereDoneThat)
  850.     {
  851.         StatusMessage(device, "\pModem driver called second time", 0);
  852.         return;
  853.     }
  854.     beenThereDoneThat = true;
  855.     
  856.     ourDeviceDescriptor = *desc;
  857.     gSerialGlobals.deviceDescriptor = &ourDeviceDescriptor;
  858.     gSerialGlobals.deviceRef = device;
  859.     
  860.     InitializePB(&syncPB, device, syncCompletion);
  861.     InitializePB(&stallPB, device, stallHandler);
  862.     stallPB.usbStatus = kAvailableStatus;
  863.     InitializePB(&delayPB, device, delayHandler);
  864.     delayPB.usbStatus = kAvailableStatus;
  865.  
  866.     InitializePB(&gSerialGlobals.pb, device, ConfigurationHandler);
  867.     gSerialGlobals.pb.usbRefcon = 1;
  868.     gSerialGlobals.pb.usbBuffer = nil;
  869.  
  870.     gSerialGlobals.retries = 10;                // Let's keep it reasonable for now
  871.     
  872.     ConfigurationHandler(&gSerialGlobals.pb);
  873. }
  874.  
  875. /************************************************************************************/
  876. //
  877. //    InitializePB
  878. //
  879. //    Initial a parameter block.
  880. //
  881. /************************************************************************************/
  882.  
  883. static void InitializePB(USBPB *pb, USBDeviceRef ref, USBCompletion handler)
  884. {
  885.     pb->pbVersion = kUSBCurrentPBVersion;
  886.     pb->pbLength = sizeof(*pb);
  887.     pb->usbReference = ref;
  888.     pb->usbCompletion = handler;
  889.     pb->usbStatus = noErr;
  890.     
  891. }
  892.  
  893. static errCount, readActive = false;
  894.  
  895. /************************************************************************************/
  896. //
  897. //    readCompletion
  898. //
  899. //    Completion handler for USB reads.
  900. //
  901. /************************************************************************************/
  902.  
  903. void readCompletion(USBPB *pb)
  904. {
  905.  
  906.     TraceMessage(0,"\pEntering readCompletion");
  907.     
  908.     readActive = false;
  909.     
  910.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  911.     {
  912.         if (pb->usbStatus == noErr){
  913.             LogData(kUSBIn, pb->usbActCount, pb->usbBuffer);
  914.             HAL_ShimInput(pb->usbBuffer, pb->usbActCount);
  915.         }else{
  916.             if ((pb->usbStatus != kUSBUnderRunErr) && errCount++ < 10)
  917.                 StatusMessage(gSerialGlobals.deviceRef, "\pRead completion error ", pb->usbStatus);
  918.                 
  919.             if (pb->usbStatus == kUSBEndpointStallErr)
  920.             {
  921. //                ClearDevice();
  922.             }
  923.             USBClearPipeStallByReference(gSerialGlobals.bulkIn);
  924.             if (pb->usbActCount > 0)
  925.                 HAL_ShimInput(pb->usbBuffer, pb->usbActCount);
  926.         }
  927.     
  928.         USBStartReadPolling();
  929.     }
  930. }
  931.  
  932. static UInt8    ioBuffer[64];
  933.  
  934. /************************************************************************************/
  935. //
  936. //    USBStartReadPolling
  937. //
  938. //    Start the USB read mechanism.
  939. //
  940. /************************************************************************************/
  941.  
  942. void USBStartReadPolling(void)
  943. {
  944.     OSStatus status;
  945.     
  946.     TraceMessage(0,"\pEntering USBStartReadPolling");
  947.     
  948.     if (gSerialGlobals.bulkIn && !readActive){
  949.         InitializePB(&readPB, gSerialGlobals.bulkIn, readCompletion);
  950.         readPB.usbBuffer = ioBuffer;
  951.         readPB.usbReqCount = sizeof(ioBuffer);
  952.         if(immediateError(status = USBBulkRead(&readPB)))
  953.         {
  954.             USBExpertFatalError(gSerialGlobals.deviceRef, status, "\pModemDriver: Couldn't start read polling", 0);
  955.             return;
  956.         }
  957.         readActive = true;
  958.     }
  959. }
  960.  
  961. /************************************************************************************/
  962. //
  963. //    USBStopReadPolling
  964. //
  965. //    You guessed it stop the USB read mechanism.
  966. //
  967. /************************************************************************************/
  968.  
  969. void USBStopReadPolling()
  970. {
  971.     StatusMessage(gSerialGlobals.deviceRef, "\pAborting Bulk-in pipe", 0);
  972.  
  973.     if (gSerialGlobals.bulkIn){
  974.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  975.     }
  976. }
  977.  
  978. static    UInt32    writeActive;
  979.  
  980. /************************************************************************************/
  981. //
  982. //    writeCompletion
  983. //
  984. //    USB write completion handler.
  985. //
  986. /************************************************************************************/
  987.  
  988. void writeCompletion(USBPB *pb)
  989. {
  990.     IOParam    *iopb;
  991.     
  992.     TraceMessage(0, "\pEntering writeCompletion");
  993.     
  994.     if (pb->usbStatus != kUSBAbortedError)    // are we being asked to quit?
  995.     {
  996.         if (pb->usbStatus != noErr) 
  997.         {
  998.             StatusMessage(gSerialGlobals.deviceRef, "\pWrite Failed", pb->usbStatus);
  999.             
  1000.             if (pb->usbStatus == kUSBEndpointStallErr)
  1001.             {
  1002. //                ClearDevice();
  1003.             }
  1004.             USBClearPipeStallByReference(pb->usbReference);
  1005.         }
  1006.     }
  1007.     writeActive--;
  1008.     gGlobals->pbOut = nil;
  1009.     iopb = (IOParam *)pb->usbRefcon;
  1010.     iopb->ioActCount = pb->usbActCount;
  1011.     
  1012.     ShimIOComplete((union ParamBlockRec *)iopb, pb->usbStatus ? ioErr : 0);
  1013.  
  1014. }
  1015.  
  1016. /************************************************************************************/
  1017. //
  1018. //    USBSerialWrite
  1019. //
  1020. //    USB serial write routine.
  1021. //
  1022. /************************************************************************************/
  1023.  
  1024. OSStatus USBSerialWrite(IOParam *pb)
  1025. {
  1026.     OSStatus     status = noErr;
  1027.     
  1028.     TraceMessage(0, "\pEntering USBSerialWrite");
  1029.     
  1030.     if (writeActive){
  1031.         StatusMessage(gSerialGlobals.deviceRef, "\pOverlapping writes!", writePB.usbStatus);
  1032.         status = ioErr;
  1033.     } else if (gSerialGlobals.bulkOut){
  1034.         
  1035.         InitializePB(&writePB, gSerialGlobals.bulkOut, writeCompletion);
  1036.         writePB.usbRefcon = (UInt32)pb;
  1037.         writePB.usbBuffer = pb->ioBuffer;
  1038.         writePB.usbReqCount = pb->ioReqCount;
  1039.         
  1040.         LogData(kUSBOut, writePB.usbReqCount, writePB.usbBuffer);
  1041.         
  1042.         if(immediateError(status = USBBulkWrite(&writePB)))
  1043.         {
  1044.             StatusMessage(gSerialGlobals.deviceRef, "\pModemDriver: Couldn't start write", status);
  1045.         } else {
  1046.             writeActive++;
  1047.             status = 1;                        // pending
  1048.         }
  1049.     } else {
  1050.         status = ioErr;
  1051.     }
  1052.     return status;
  1053. }
  1054.  
  1055. /************************************************************************************/
  1056. //
  1057. //    KillUSBIO
  1058. //
  1059. //    Kill all USB io operations in progress.
  1060. //
  1061. /************************************************************************************/
  1062.  
  1063. void KillUSBIO(void)
  1064. {
  1065.     IOParam             *pb;
  1066.     ShimSerialGlobals     *globals = gGlobals;
  1067.     
  1068.     StatusMessage(gSerialGlobals.deviceRef, "\pModem: Killing all USB IO", 0);
  1069.  
  1070.     if (gSerialGlobals.bulkIn){
  1071.         USBAbortPipeByReference(gSerialGlobals.bulkIn);
  1072.         gSerialGlobals.bulkIn = nil;
  1073.     }
  1074.     if (gSerialGlobals.bulkOut){
  1075.         USBAbortPipeByReference(gSerialGlobals.bulkOut);
  1076.         gSerialGlobals.bulkOut = nil;
  1077.     }
  1078.     if (gSerialGlobals.interrupt){
  1079.         USBAbortPipeByReference(gSerialGlobals.interrupt);
  1080.         gSerialGlobals.interrupt = nil;
  1081.     }
  1082.     
  1083.     pb = (IOParam *)globals->pbIn;
  1084.     if (pb) {
  1085.         ShimIOComplete((union ParamBlockRec *)pb, ioErr);
  1086.         globals->pbIn = nil;
  1087.     }
  1088.     pb = (IOParam *)globals->pbOut;
  1089.     if (pb) {
  1090.         ShimIOComplete((union ParamBlockRec *)pb, ioErr);
  1091.         globals->pbOut = nil;
  1092.     }
  1093. }
  1094.  
  1095. /************************************************************************************/
  1096. //
  1097. //    InitLineCoding
  1098. //
  1099. //    Store the initial line settings.
  1100. //
  1101. /************************************************************************************/
  1102.  
  1103. void InitLineCoding(LineParms Line_Coding)
  1104. {
  1105.     serPB     *sp = &gSerialGlobals;
  1106.     
  1107.     TraceMessage(0, "\pEntering InitLineCoding");
  1108.         
  1109.     // save the settings
  1110.     sp->Line_Settings.DTERate1 = Line_Coding.DTERate1;
  1111.     sp->Line_Settings.DTERate2 = Line_Coding.DTERate2;
  1112.     sp->Line_Settings.CharFormat = Line_Coding.CharFormat;
  1113.     sp->Line_Settings.ParityType = Line_Coding.ParityType;
  1114.     sp->Line_Settings.DataBits = Line_Coding.DataBits;
  1115. }
  1116.  
  1117. /************************************************************************************/
  1118. //
  1119. //    DoDelay
  1120. //
  1121. //    Set up to do a USB delay.
  1122. //
  1123. /************************************************************************************/
  1124.  
  1125. void DoDelay(void)
  1126. {
  1127. serPB     *sp = &gSerialGlobals;
  1128.     
  1129.     TraceMessage(0, "\pEntering DoDelay");
  1130.     
  1131.     if (TimeoutDelayRequest())
  1132.         return;
  1133.             
  1134.     delayPB.usbStatus = noErr;
  1135.     delayPB.usbReference = sp->deviceRef;
  1136.     delayPB.usbRefcon = 1;
  1137.     delayPB.usbReqCount = 5;            // ~5ms (actually 5 frames at 1ms each)
  1138.     USBDelay(&delayPB);    
  1139. }
  1140.  
  1141. /************************************************************************************/
  1142. //
  1143. //    delayHandler
  1144. //
  1145. //    Completion handler for USB delay.
  1146. //
  1147. /************************************************************************************/
  1148.  
  1149. static void delayHandler(USBPB *pb)
  1150. {
  1151. serPB     *sp = &gSerialGlobals;
  1152.  
  1153.     TraceMessage(0, "\pEntering delayHandler");
  1154.  
  1155.     if (pb->usbStatus != noErr)
  1156.         StatusMessage(sp->deviceRef, "\pModemDriver: Delay fail?", pb->usbStatus);
  1157.  
  1158.     pb->usbStatus = kAvailableStatus;
  1159. }
  1160.  
  1161. /************************************************************************************/
  1162. //
  1163. //    ClearDevice
  1164. //
  1165. //    Set up and send ClearFeature request (for stall).
  1166. //
  1167. /************************************************************************************/
  1168.  
  1169. void ClearDevice(void)
  1170. {
  1171. serPB     *sp = &gSerialGlobals;
  1172.  
  1173.     TraceMessage(0, "\pEntering ClearDevice");
  1174.     
  1175.     if (TimeoutStallRequest())
  1176.         return;
  1177.         
  1178.     stallPB.usbStatus = noErr;
  1179.     stallPB.usbReference = sp->deviceRef;
  1180.     stallPB.usbRefcon = 1;
  1181.     stallHandler(&stallPB);
  1182. }
  1183.  
  1184. /************************************************************************************/
  1185. //
  1186. //    stallHandler
  1187. //
  1188. //    Completion handler for clear device/stall.
  1189. //
  1190. /************************************************************************************/
  1191.  
  1192. static void stallHandler(USBPB *pb)
  1193. {
  1194. serPB         *sp = &gSerialGlobals;
  1195. OSStatus    err = 0;
  1196.  
  1197.     TraceMessage(0, "\pEntering StallHandler");
  1198.     
  1199.     if (pb->usbStatus != noErr)
  1200.     {
  1201.         USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pModemDriver: Stall fail?", pb->usbRefcon);
  1202.         return;
  1203.     }
  1204.     
  1205.     // May have to do more here (like find out which endpoint is stalled) which is why an FSM is used
  1206.     // For the moment it's the Comm Class endpoint 0 which we'll try to clear (interupptComplete only for now)
  1207.     do{switch(pb->usbRefcon++)
  1208.     {
  1209.         case kEndpointStall:
  1210.             pb->usbStatus = noErr;
  1211.             pb->usbReference = sp->deviceRef;
  1212.             pb->pbVersion = kUSBCurrentPBVersion;    
  1213.             pb->usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBEndpoint);
  1214.     
  1215.             pb->usbBRequest = kUSBRqClearFeature;
  1216.             pb->usbWValue = 0;                        // Endpoint stall
  1217.             pb->usbWIndex = 0;
  1218.             pb->usbReqCount = 0;
  1219.             pb->usbBuffer = nil;
  1220.  
  1221.             if(immediateError(err = USBDeviceRequest(pb)))
  1222.             {
  1223.                 StatusMessage(sp->deviceRef, "\pModem driver clearing device stall error", err);
  1224.             }
  1225.         break;
  1226.         
  1227.         case kStallDone:
  1228.         // stall should now be cleared
  1229.             if (pb->usbStatus != noErr)
  1230.                 USBExpertFatalError(sp->deviceRef, pb->usbStatus, "\pModemDriver: stall handler err for bRequest", pb->usbBRequest);
  1231.     
  1232.             pb->usbStatus = kAvailableStatus;
  1233.         break;
  1234.         
  1235.         default:
  1236.             StatusMessage(sp->deviceRef, "\pInternal Error unused case in stall handler", (pb->usbRefcon-1));
  1237.         break;
  1238.     }
  1239.     break;    /* only execute once, unless continue used */
  1240.     }while(1);    /* so case can be reentered with a continue */
  1241. }
  1242.  
  1243. #if ((DebugOn > 0) && (LogOn > 0))
  1244.  
  1245. /************************************************************************************/
  1246. //
  1247. //    Asciify
  1248. //
  1249. //    Convert to Ascii character
  1250. //
  1251. /************************************************************************************/
  1252.  
  1253. UInt8 Asciify(UInt8 i)
  1254. {
  1255.  
  1256.     i &= 0xF;
  1257.     if ( i < 10 )
  1258.          return( '0' + i );
  1259.     else return( 55  + i );
  1260.     
  1261. }
  1262.  
  1263. #define dumplen        16        // Set this to the number of bytes to dump and the rest should work out correct
  1264.  
  1265. #define buflen        ((dumplen*2)+dumplen)+3
  1266. #define Asciistart    (dumplen*2)+3
  1267.  
  1268. /************************************************************************************/
  1269. //
  1270. //    USBLogData
  1271. //
  1272. //    Dumps the requested amount of data to the USB Expert log.
  1273. //
  1274. /************************************************************************************/
  1275.  
  1276. void USBLogData(UInt8 Dir, UInt32 Count, UInt8 *buf)
  1277. {
  1278.     UInt8    wlen, i, Aspnt, Hxpnt;
  1279.     UInt8    wchr;
  1280.     UInt8    LocBuf[buflen];
  1281.  
  1282.     for ( i=1; i<=buflen; i++)
  1283.     {
  1284.         LocBuf[i] = 0x20;
  1285.     }
  1286.     
  1287.     if (Dir == kUSBIn)
  1288.     {
  1289.         TraceMessage(1, "\pRead Complete");
  1290.     } else {
  1291.         TraceMessage(1, "\pWrite");
  1292.     }
  1293.  
  1294.     if (Count > dumplen)
  1295.     {
  1296.         wlen = dumplen;
  1297.     } else {
  1298.         wlen = Count;
  1299.     }
  1300.     
  1301.     if (wlen > 0)
  1302.     {
  1303.         Aspnt = Asciistart;
  1304.         Hxpnt = 1;
  1305.         for (i=1; i<=wlen; i++)
  1306.         {
  1307.             wchr = buf[i-1];
  1308.             LocBuf[Hxpnt++] = Asciify(wchr >> 4);
  1309.             LocBuf[Hxpnt++] = Asciify(wchr);
  1310.             if ((wchr < 0x20) || (wchr == 0x7F))         // Non printable characters
  1311.             {
  1312.                 LocBuf[Aspnt++] = 0x2E;                    // Replace with a period
  1313.             } else {
  1314.                 LocBuf[Aspnt++] = wchr;
  1315.             }
  1316.         }
  1317.         LocBuf[0] = (wlen + Asciistart) + 1;
  1318.         TraceMessage(1, LocBuf);
  1319.     } else {
  1320.         TraceMessage(1, "\pNo data - Actual count=0");
  1321.     }
  1322. }
  1323. #endif